			OUTPUT "g9bview.com"
			
			DEFINE	G9K_DISABLE_CURSOR
			DEFINE  G9K_DISABLE_PATTERN
			DEFINE  G9K_DISABLE_VFF_VRAM ; Only use ram fonts
			DEFINE  BITBUSTER_OPTIMIZE_SPEED
					
			include	"g9klib.inc"
			include "bdos.inc"
			include "macros.inc"
			include "keyboard.inc"
			include "bios.inc"

; Info window size
WINDOW_TOP	EQU	100
WINDOW_LEFT	EQU	10
WINDOW_WIDTH	EQU	23*8 + 2 ; 2 is extra space around the text
WINDOW_HEIGHT	EQU	6*8 + 4

			
			STRUCT MODE_TABLE
width	  	        WORD
height			WORD
mode			BYTE			
	                ENDS 
	                					
			org     0100h
			
G9BViewMain:
			CALL    G9k.Detect
			JP      NZ,NoGfx9kDetected
			CALL    G9k.Reset
			
			LD	A,(CMD_LENGTH)
			OR	A,A
			JP	Z,PrintHelp
			
			G9kWriteReg G9K_ARG,0
			G9kWriteReg G9K_LOP,G9K_LOP_WCSC
			LD      HL,#FFFF
			CALL    G9k.SetCmdWriteMask
					
			LD	DE,CMD_LINE
			CALL	FindFirst
			JP	NZ,.ErrorOpening
					
			CALL	LoadFont
			JP	NZ,ErrorFont
						
			; Calculate free ram pointer
			LD	HL,(font.dataSize)
			LD	DE,DATA_BUFFER  ; Pointer to buffer 
			ADD	HL,DE
			LD	(freeRamAddr),HL
			
			; Reserve 256 bytes stack space
			LD	HL,-256
			ADD	HL,SP		
			LD	DE,(freeRamAddr)
			OR	A,A
			SBC	HL,DE
			LD	(freeRamSize),HL
				
.viewLoop			
			LD	HL,G9BObject
			LD	DE,fib
			CALL	G9k.OpenG9B			
			JP	NZ,.ErrorOpening
			
			; Reset scroll position
			LD	HL,0
			CALL    G9k.SetScrollY
			CALL    G9k.SetScrollX
			
			LD	HL,WINDOW_LEFT
			LD	(vramCopy.left),HL
			LD	HL,WINDOW_TOP
			LD	(vramCopy.top),HL		
			
			G9kWaitVsync	
			CALL	G9k.DisplayDisable
			; set backdrop color on 0
			G9kWriteReg G9K_PALETTE_PTR,0
			XOR	A,A
			OUT	(G9K_PALETTE),A     
			OUT	(G9K_PALETTE),A     
			OUT	(G9K_PALETTE),A     
			CALL	G9k.SetBackDropColor
	
			LD	IX,G9BObject
			CALL	G9BViewSetScreenMode
	
			LD	DE,(freeRamAddr)
			LD	IX,G9BObject       ; Pointer to G9B object
			LD	C,0		   ; Palette pointer	
			CALL	G9k.ReadG9BPalette
			JR	NZ,.ErrorLoading
			
			CALL	DuplicatePalette 
			CALL	GetBestFontColors
			CALL	G9BClearScreen
			
			G9kCmdWait
			CALL	G9k.DisplayEnable
				
			CALL	G9BCenterPicture ; Returns HL= X pos, IY = Y pos							
			LD	DE,(freeRamAddr)
			LD	IX,G9BObject     ; Pointer to G9B object
	                LD	BC,(freeRamSize) ; Buffer size
	                LD	A,255	         ; Palette pointer. Don't read palette
			CALL	G9k.ReadG9B
			JR	NZ,.ErrorLoading
.close			
			LD	IX,G9BObject     ; Pointer to G9B object	
			CALL	G9k.Close
			
			CALL	GetG9BInfo
			CALL	CalcBackDataSize
			G9kCmdWait
			
			LD	A,(showInfo)
			OR	A,A
			JR	Z,.noFileInfo
			
			CALL	SaveBackGrnd
			CALL	G9BViewFileInfo
.noFileInfo			
			PUSH	AF
			CALL	CalcMaxScroll			
			CALL	KeyScan
			POP	AF
			JR	Z,.next
		
			CALL	RestoreBackGrnd
.next				
			CALL	FindNext
			CP	A,ERROR.NOFIL
			JR	Z,Exit
			JP	.viewLoop
									
.ErrorLoading
			CALL	 PrintError	
			JR	 .close
.ErrorOpening
			CP	A,_NOG9B
			JR	Z,.NotAG9bFile
			JP	PrintError
.NotAG9bFile
			LD	DE,NO_G9B_TXT
			CALL	String.PrintAsciiz
			JR	.close

freeRamAddr		DW	0
freeRamSize		DW	0			
			
NO_G9B_TXT		DB	  "File is not a G9B file",CR,LF,0		

Exit:			
			BIOS	KILBUF
			BdosCall _TERM
			RET				
PrintError:
			LD	  DE,Bdos.ERROR_STRING
			CALL	  String.PrintAsciiz
			LD	  DE,NEW_LINE
			CALL	  String.PrintAsciiz
			RET
			
ErrorFont:
			LD	  DE,.FONT_ERR_TXT
			CALL	  String.PrintAsciiz
			LD	  DE,fontName
			CALL	  String.PrintAsciiz	
			LD	  DE,NEW_LINE
			CALL	  String.PrintAsciiz			
	
			LD	  DE,Bdos.ERROR_STRING
			CALL	  String.PrintAsciiz	
	
			LD	  DE,NEW_LINE
			CALL	  String.PrintAsciiz
			RET
			
.FONT_ERR_TXT:		DB	"*** Error loading font - ",0


G9BViewSetScreenMode:
			LD	A,(IX+G9B_OBJECT.bitDepth)
			SRA	A
			LD	HL,G9B_VIEW_BIT_DEPTH
			ADD_HL_A
			LD	B,(HL)	; Color depth
			INC	HL
			LD	C,(HL)  ; Image size	
			;Width 8bit mode it usefull to switch to image size 1024 if width>height
			LD	A,B
			CP	A,G9K_SCR0_8BIT
			JR	NZ,.no8Bit
			LD      HL,(IX+G9B_OBJECT.width)
			LD	DE,(IX+G9B_OBJECT.height)
			OR	A,A
			SBC	HL,DE
			JR	C,.no8Bit
			LD	C,G9K_SCR0_XIM1024		
.no8Bit		
			LD	DE,(IX+G9B_OBJECT.width)
			LD	A,(IX+G9B_OBJECT.bitDepth)
			CALL    G9BGetGfxMode 
			LD	(currentMode),A
			LD	DE,(IX+G9B_OBJECT.height)
			OR	A,A
			SBC	HL,DE
			LD	D,0
			JR	NC,.nonInterlaced
			LD	HL,(currentG9kHeight)	
			ADD	HL,HL;  height * 2
			LD	(currentG9kHeight),HL			
			LD	D,1
.nonInterlaced:			
			LD      E,(IX+G9B_OBJECT.colorType)		
			JP      G9k.SetScreenMode		
			

			
G9B_VIEW_BIT_DEPTH	DB	G9K_SCR0_2BIT,G9K_SCR0_XIM1024		
			DB	G9K_SCR0_4BIT,G9K_SCR0_XIM1024		
			DB	G9K_SCR0_8BIT,G9K_SCR0_XIM512           
			DB	0,0                              
			DB	G9K_SCR0_16BIT,G9K_SCR0_XIM512               

currentG9kWidth		DW	0	
currentG9kHeight	DW 	0
currentMode		DB	0  


G9BGetGfxMode:
; In    DE = width of G9B file
;        A = color depth
; Output A = gfx mode
;       HL = height from gfx mode
;       DE  = width from gfx mode
			PUSH	BC
			; check if bithdepth is higher or equal then 8 bit. In that case b4 and b7 are invalid 
			CP	A,8
			LD	B,4
			JR	C,.lowerThen8bit	
			LD	B,2
			
.lowerThen8bit			
			LD	IY,.modeTable
.loop			
			LD	HL,(IY + MODE_TABLE.width)
			OR	A,A
			SBC	HL,DE
			JR	NC,.end
			
			EX	DE,HL
			LD	DE,MODE_TABLE ; size of mode table struct
			ADD	IY,DE
			EX	DE,HL	
			DJNZ	.loop 
.end
			LD	A, (IY + MODE_TABLE.mode)
			LD	DE,(IY + MODE_TABLE.width)
			LD	(currentG9kWidth),DE
			LD	HL,(IY + MODE_TABLE.height)
			LD	(currentG9kHeight),HL
			POP	BC
			RET

.modeTable              MODE_TABLE 256, 212,G9K_MODE_B1
			MODE_TABLE 384, 240,G9K_MODE_B2
			MODE_TABLE 512, 212,G9K_MODE_B3
			MODE_TABLE 768, 240,G9K_MODE_B4
			MODE_TABLE 1024,212,G9K_MODE_B7

G9BCenterPicture:
; Input IX = Pointer to G9B object
; Output HL = X
;        IY = Y 

.width	
			LD	DE,(currentG9kWidth)
			LD	HL,(IX+G9B_OBJECT.width)
			OR	A,A
			SBC	HL,DE
			; If carry is not set then there is no width centering needed
			LD	HL,0
			JR	NC,.height	 
			
			LD	HL,(IX+G9B_OBJECT.width)
			EX	DE,HL
			OR	A,A
			SBC	HL,DE
			SRA	HL		; G9kWidth - G9bWidth /2			
.height			
			PUSH	HL	
			LD	DE,(currentG9kHeight)
			LD	HL,(IX+G9B_OBJECT.height)
			OR	A,A
			SBC	HL,DE
			; If carry is not set then there is no height centering needed
			LD	IY,0
			JR	NC,.end	 
			
			LD	HL,(IX+G9B_OBJECT.height)
			EX	DE,HL
			OR	A,A
			SBC	HL,DE
			SRA	HL		; G9kHeight- G9bheight /2	
			LD	IY,HL		
.end
			POP	HL	
			RET		
G9BClearScreen:
; TODO: Clear image size	
			LD      HL,clearScreen
			LD	DE,(backGroundColor)
			JP      G9k.DrawFilledBox  

clearScreen		G9K_BOX	0,0,1024,512	


DuplicatePalette:

			LD	A,(currentMode)
			CP	A,G9K_MODE_B4
			RET	C
			
			; Copy palette for b4 to b7 
			LD	B,16*3
			LD	C,0
			LD	HL,(freeRamAddr)
			PUSH	HL
			CALL	G9k.ReadPalette
			POP	HL
			LD	B,16*3
			LD	C,4*32
			JP	G9k.WritePalette
			
CalcMaxScroll:
; Input IX = Pointer to g9b object		
			
			; Check if Y scrolling is needed 
			LD	HL,0
			LD	(maxX),HL
			LD	(maxY),HL
			LD  	HL,(currentG9kHeight)
			LD  	DE,(IX+G9B_OBJECT.height)
			PUSH	HL
			SBC 	HL,DE
			POP	HL	 ;  display height - g9b object height
			JR      NC,.calcMaxX
			
			EX	DE,HL
			OR  	A,A
			SBC 	HL,DE    ; Maximum scroll value
			LD	(maxY),HL
.calcMaxX			
			LD  	HL,(currentG9kWidth)
			LD  	DE,(IX+G9B_OBJECT.width)
			PUSH	HL
			SBC 	HL,DE
			POP	HL	 ;  display width - g9b object width
			RET	NC
			EX	DE,HL
			OR  	A,A
			SBC 	HL,DE    ; Maximum scroll value
			LD	(maxX),HL
			RET
							
KeyScan:			
			LD	DE,0      ; Current X scroll offset
			LD	IY,0      ; Current Y scroll offset

.keyScan		
			LD	C,7
			CALL    Keyboard.GetDirectKey
			BIT	KEY_ESC,A
			JP	Z,Exit
	
			LD	C,8
			CALL    Keyboard.GetDirectKey
			BIT	KEY_SPACE_BAR,A
			RET	Z			
			
			LD	HL,.next
			PUSH	HL
				
			BIT	KEY_LEFT,A
			JP	Z,Left
			
			BIT	KEY_RIGHT,A
			JP	Z,Right

			BIT	KEY_UP,A
			JP	Z,Up
			
			BIT	KEY_DOWN,A
			JP	Z,Down
			
			BIT	KEY_HOME,A
			JP	Z,ShowFileInfo
			
			POP	HL
				
.next			
			JP	.keyScan
			
; Scroll Y 							
Up
			PUSH	AF	
					
			PUSH	DE
			LD	HL,(maxY)
			OR	A,A
			EX	DE,HL			
			SBC	HL,DE	
			POP	DE
			
			JR	NC,.noScrollY
			INC	DE
			
			LD	A,(showInfo)
			OR	A,A
			JR	Z,.noFileInfo
								
			PUSH	IY
			PUSH	DE
			CALL	RestoreBackGrnd
			LD	HL,WINDOW_TOP
			ADD	HL,DE
			LD	(vramCopy.top),HL
			CALL	SaveBackGrnd
			CALL	G9BViewFileInfo
			POP	DE
			POP	IY	
			
.noFileInfo					
			POP	AF
			JR      Down.SetScrollY
.noScrollY		
			POP	AF
			RET			
			

			
Down			
			PUSH	AF
			LD	A,D
			OR	A,E
			JR	Z,.noScrollY				
			DEC	DE
			
			LD	A,(showInfo)
			OR	A,A
			JR	Z,.noFileInfo
			
			PUSH	IY
			PUSH	DE
			CALL	RestoreBackGrnd
			LD	HL,WINDOW_TOP
			ADD	HL,DE
			LD	(vramCopy.top),HL
			CALL	SaveBackGrnd
			CALL	G9BViewFileInfo
			POP	DE
			POP	IY
.noFileInfo			
			POP	AF
.SetScrollY
			LD	HL,DE
			PUSH	AF	
			G9kWaitVsync
			CALL    G9k.SetScrollY
.noScrollY	
			POP	AF
			RET	
	
			
; Scroll X 				
Left:
			PUSH	AF
			LD	BC,(maxX) 
			LD	HL,IY
			OR	A,A
			SBC	HL,BC
			
			JR	NC,.noScrollX
			INC	IY

			LD	A,(showInfo)
			OR	A,A
			JR	Z,.noFileInfo

			PUSH	IY
			PUSH	DE
			CALL	RestoreBackGrnd
			LD	BC,WINDOW_LEFT
			ADD	IY,BC
			LD	(vramCopy.left),IY
			CALL	SaveBackGrnd
			CALL	G9BViewFileInfo
			POP	DE
			POP	IY
.noFileInfo			
			POP	AF
			JR      Right.SetScrollX
.noScrollX		
			POP	AF
			RET	
			
Right:
			PUSH	AF
			LD	A,IYH
			OR	A,IYL
			JR	Z,.noScrollX	
			DEC	IY
			
			LD	A,(showInfo)
			OR	A,A
			JR	Z,.noFileInfo
			
			PUSH	IY
			PUSH	DE
			CALL	RestoreBackGrnd
			LD	BC,WINDOW_LEFT
			ADD	IY,BC
			LD	(vramCopy.left),IY
			CALL	SaveBackGrnd
			CALL	G9BViewFileInfo
			POP	DE
			POP	IY
.noFileInfo			
			POP	AF
.SetScrollX
			LD	HL,IY
			PUSH	AF	
			G9kWaitVsync
			CALL    G9k.SetScrollX
.noScrollX			
			POP	AF
			RET	
			
ShowFileInfo:
			PUSH	AF
			PUSH	IY
			PUSH	DE	
	
			LD	A,(showInfo)
			OR	A,A
			JR	Z,.showInfo
						
			CALL	RestoreBackGrnd
			JP	.setNewState
.showInfo
			LD	BC,WINDOW_LEFT
			ADD	IY,BC
			LD	(vramCopy.left),IY
			
			LD	HL,WINDOW_TOP
			ADD	HL,DE
			LD	(vramCopy.top),HL
			
			CALL	SaveBackGrnd
			CALL	G9BViewFileInfo

.setNewState
			LD	A,(showInfo)
			XOR	A,1
			LD	(showInfo),A

; Wait key released
.waitReleased
			LD	C,8			
			CALL    Keyboard.GetDirectKey
			BIT	KEY_HOME,A
			JP	Z,.waitReleased
			
			POP	DE
			POP	IY		
			POP	AF
			RET
			
showInfo		DB	0			
						
maxY			DW	0			
maxX			DW	0						



;------------------------------------------------
;--- File info window
;------------------------------------------------
G9BViewFileInfo:
; Input  IX = Pointer to G9B_OBJECT
			PUSH	IX   
			LD	DE,(backGroundColor)
			LD	HL,vramCopy  ;Use same parameters used by RestoreBackground
			CALL    G9k.DrawFilledBox
			
			;File   Name
		        LD	DE,.FILE_TXT
	                LD 	IY,(vramCopy.top)
	                INC	IY
	                INC	IY
        	        LD	IX,(vramCopy.left)   
        	        INC	IX     	    
        	        INC	IX     	
        	        
        	      	G9kCmdWait
        	      	
			LD      HL,(backGroundColor)
	                CALL 	G9k.SetCmdBackColor
	                	             	           
        	        LD      HL,(fontColor)
                	CALL    G9k.SetCmdColor  
        	            
        	        CALL	G9k.PrintString 

			LD	DE,7*8			
	 	        ADD	IX,DE
	 			        
		        LD	DE,fib.fileName
        	        CALL	G9k.PrintString 

        	        ; Resolution width
        	        LD	DE,1*8          
        	        ADD	IY,DE		; Next line
        	        
		        LD	DE,.WIDTH_TXT
	                LD 	IX,(vramCopy.left) 
                    	INC	IX     	    
        	        INC	IX  
        	        CALL	G9k.PrintString 
        	        
			LD	DE,6*8	
        	        ADD	IX,DE 		
			LD	DE,G9B_WIDTH
			CALL	G9k.PrintString  
			
	       	        ; Resolution height
        	        LD	DE,1*8
        	        ADD	IY,DE		; Next line
        	        
		        LD	DE,.HEIGHT_TXT
	                LD 	IX,(vramCopy.left) 
                    	INC	IX     	    
        	        INC	IX  
        	        CALL	G9k.PrintString 
        	        
			LD	DE,5*8	
        	        ADD	IX,DE 		
			LD	DE,G9B_HEIGHT
			CALL	G9k.PrintString  
			
        	        LD	DE,1*8
        	        ADD	IY,DE		; Next line
		        LD	DE,.BIT_PER_PIXEL_TXT
	                LD 	IX,(vramCopy.left) 
                    	INC	IX     	    
        	        INC	IX  	                
        	        CALL	G9k.PrintString 
			
			LD	DE,8*8	
        	        ADD	IX,DE 		
			LD	DE,G9B_BITDEPTH     	    
        	        CALL	G9k.PrintString  
			
			LD	A,(G9BObject.bitDepth)
			CP	A,8
			CALL	Z,Get8bitColorMode
			
			
		        LD	DE,1*8
        	        ADD	IY,DE		; Next line
        	        
		        LD	DE,.COMPRESSION_TXT
	                LD 	IX,(vramCopy.left) 
                    	INC	IX     	    
        	        INC	IX  
        	        CALL	G9k.PrintString 
	
  	      		LD	DE,1*8	
        	        ADD	IX,DE 		

			LD	A,(G9BObject.compression)
			OR	A,A
			LD	DE,.YES_TXT
			JR	NZ,.a
			LD	DE,.NO_TXT
.a			
        	        CALL	G9k.PrintString 
        	        
            		LD	DE,1*8
        	        ADD	IY,DE		; Next line
        	           
		        LD	DE,.DATA_SIZE_TXT
	                LD 	IX,(vramCopy.left) 
                    	INC	IX     	    
        	        INC	IX  
        	        CALL	G9k.PrintString 
        	        	
        	      	LD	DE,7*8	
        	        ADD	IX,DE 		
			LD	DE,G9B_SIZE     	    
        	        CALL	G9k.PrintString  
			
			POP	IX
			
			RET

			
			
.FILE_TXT		DB	"File",0
.WIDTH_TXT		DB	"Width",0
.HEIGHT_TXT		DB	"Height",0
.BIT_PER_PIXEL_TXT	DB	"Bpp",0
.DATA_SIZE_TXT		DB	"Size",0

.COMPRESSION_TXT	DB	"Compressed",0
.YES_TXT		DB	"Yes",0
.NO_TXT			DB	"No",0

GetG9BInfo:		
			LD	HL,(G9BObject.width)
			LD	DE,G9B_WIDTH
        	        CALL	String.UnsignedInt16ToStr
	 	   
        	        LD	HL,(G9BObject.height)     
        	        LD	DE,G9B_HEIGHT
              	        CALL	String.UnsignedInt16ToStr
   	        
        	 	LD	A,(G9BObject.bitDepth)
			LD	L,A
			LD	H,0
	  	        LD	DE,G9B_BITDEPTH
        	        CALL	String.UnsignedInt16ToStr
		        
        		LD	HL,(G9BObject.dataSize)
        		LD	A,(G9BObject.dataSize + 2)
        		EXX	
        		LD	L,A
        		LD	H,0
        		EXX
   		     	LD	DE,G9B_SIZE
        	        CALL	String.UnsignedInt32ToStr
			RET
			
G9B_WIDTH		DS	6,0
G9B_HEIGHT		DS	6,0
G9B_BITDEPTH		DS	4,0
G9B_SIZE		DS	9,0

Get8bitColorMode:
			LD	A,(G9BObject.colorType)
			RLCA
			RLCA
			AND	A,3		
			ADD	A,A
			LD	HL,.colorModes
			ADD_HL_A
			LD	DE,1*8	
        	        ADD	IX,DE 
        	        	
  	      		LD	DE,(HL)
			CALL	G9k.PrintString  
			RET

.colorModes		DW	.palette,.fixed,.YJK,.YUV

			
.palette		DB	"(64 color)",0
.fixed			DB      "(Fixed)",0
.YJK			DB	"(YJK)",0
.YUV			DB	"(YUV)",0

GetBestFontColors:
			LD	A,(G9BObject.bitDepth)
			CP	A,16
			JR	Z,.fixedColors
			CP	A,8
			JR	Z,.color8bit					
			JP	.getPaletteColors
			
.color8bit
			LD	A,(G9BObject.colorType)
			OR	A,A
			JP	Z,.getPaletteColors

.fixedColors			
			LD	HL,0
			LD	(backGroundColor),HL
			LD	HL,0FFFFH
			LD	(fontColor),HL
			RET
			
.getPaletteColors
			LD	A,(G9BObject.bitDepth)
			CALL	GetNrOfColors
			
			PUSH	BC
			
			LD	A,B
			ADD	A,A
			ADD	A,B ;* 3
			LD 	B,A
			
			LD	HL,DATA_BUFFER
			LD	C,0
			CALL	G9k.ReadPalette
			POP	BC
			
			PUSH	BC
			LD	HL,DATA_BUFFER
			LD	C,0		; current color index
			LD	E,0		; color value
			LD	D,0		; highest color index
.getHighest:			
			LD	A,(HL)
			INC	HL
			ADD	A,(HL)
			INC	HL
			ADD	A,(HL)
			INC	HL		; sum  r + g + b
			CP	A,E
			JP	C,.next1
			LD	D,C
			LD	E,A
.next1				
			INC	C
			DJNZ	.getHighest
			
			CALL	MakeCmdColor
			LD	(fontColor),HL
			POP	BC
			
			
			LD	HL,DATA_BUFFER
			LD	C,0		; current color index
			LD	E,255		; cumulative color value
			LD	D,0		; highest color index
.getLowest:			
			LD	A,(HL)
			INC	HL
			ADD	A,(HL)
			INC	HL
			ADD	A,(HL)
			INC	HL		; sum  r + g + b
			CP	A,E
			JP	NC,.next2
			LD	D,C
			LD	E,A
.next2			
			INC	C
			DJNZ	.getLowest
			
			LD	A,D
			PUSH	AF
			CALL	MakeCmdColor
			LD	(backGroundColor),HL	
			POP	AF; = background color index
			CALL	G9k.SetBackDropColor		; Set back drop color same as window back ground color		
			RET

		
GetNrOfColors:
; Input  A = bits per pixel
; Output B = nr Of colors
			LD	B,64
			CP	A,8
			RET	Z			
			LD	B,16
			CP	A,4
			RET	Z
			LD	B,4
			RET
			
MakeCmdColor:		
; Input  D = Color index	
; Output HL = cmd color
			LD	A,(G9BObject.bitDepth)				
			CP	A,8
			JP	NZ,.a
			LD	L,D
			LD	H,D
			RET
.a			
			CP	A,4
			JP	NZ,.b
			LD	A,D
			AND	A,0xF
			LD	B,A
			ADD	A,A
			ADD	A,A
			ADD	A,A
			ADD	A,A
			OR	A,B
			LD	L,A
			LD	H,A
			RET		
.b			
			LD	A,D
			ADD	A,A
			ADD	A,A
			OR	A,D
			ADD	A,A
			ADD	A,A
			OR	A,D
			ADD	A,A
			ADD	A,A
			OR	A,D
			LD	L,A
			LD	H,A
			RET						
			
backGroundColor		DW	0
fontColor		DW	0FFFFh

					
SaveBackGrnd:		

			LD	HL,vramCopy
			CALL	G9k.SetupCopyXYToRam
			G9kWaitComReady
			LD	BC,(backGrndDataSize)
			LD	HL,(freeRamAddr)
			JP 	G9k.CopyXYToRam	
			;JP	CopyXYToRam
/*			
CopyXYToRam:
; HL = Pointer to data
; BC = Bytes to copy
		
			PUSH	IX
			LD      A,B
			LD      B,C
			INC     B
			DEC     B
			JR      Z,$+3
	                    INC    A
	                LD      C,G9K_CMD_DATA
	             
	                PUSH	AF
	                PUSH	DE
	                
	                XOR	A,A
	                SUB	A,B                
	                LD	IXL,A
	                LD	IXH,0
	                ADD	IX,IX
	                LD	DE,.loop
	                ADD	IX,DE
	                
	                POP	DE
	                POP	AF
	                
	                JP	(IX)
	                
.loop             
	                REPT 256
			INI
			ENDM
		
	                DEC     A
	                JP   	NZ,.loop 
	                POP	IX 
	                RET			
*/					
RestoreBackGrnd:
			
			LD	HL,vramCopy
			CALL	G9k.SetupCopyRamToXY
			G9kWaitComReady	
			LD	BC,(backGrndDataSize)
			LD	HL,(freeRamAddr)
			JP	G9k.CopyRamToXY
			;JP	CopyRamToXY

/*
CopyRamToXY:
; HL = Pointer to data
; BC = Bytes to copy
		
			PUSH	IX
			LD      A,B
			LD      B,C
			INC     B
			DEC     B
			JR      Z,$+3
	                   INC    A
	                LD      C,G9K_CMD_DATA
	             
	                PUSH	AF
	                PUSH	DE
	                
	                XOR	A,A
	                SUB	A,B                
	                LD	IXL,A
	                LD	IXH,0
	                ADD	IX,IX
	                LD	DE,.loop
	                ADD	IX,DE
	                
	                POP	DE
	                POP	AF
	                
	                JP	(IX)
	                
.loop             
	                REPT 256
			OUTI
			ENDM
		
	                DEC     A
	                JP   	NZ,.loop 
	                POP	IX 
	                RET

*/

CalcBackDataSize:
; IX Pointer to g9b object
			LD	HL,WINDOW_WIDTH * WINDOW_HEIGHT /2 ; Data size of 4 bit
			LD	A,(IX + G9B_OBJECT.bitDepth)	
			CP	A,4
			JR	Z,.setSize
			ADD	HL,HL
			CP	A,8
			JR	Z,.setSize
			ADD	HL,HL  ; 16 bit
.setSize
			LD	(backGrndDataSize),HL					
			RET
			
backGrndDataSize	DW	0

vramCopy		G9K_BOX	WINDOW_LEFT,WINDOW_TOP,WINDOW_WIDTH,WINDOW_HEIGHT					
			
;------------------------------------------------
;--- Load font
;------------------------------------------------


LoadFont:
			; Get fontname relative to start path
			LD	DE,startPath
			CALL	GetStartPath
			; HL = pointer to start of last item
			EX	DE,HL
			LD	HL,fontName
			LD	BC,12
			LDIR	; concat font file name to start path
			
			LD	DE,startPath
			LD	IX,font
		        LD	A,1     ; Font in ram
	                CALL    G9k.OpenVff
	                RET	NZ	; Return if error loading font
	                	                
			LD	IY,FONT_OFFSET_TABLE
	                LD	IX,font
	                LD	HL,DATA_BUFFER
	                LD	BC,8000h
	                CALL    G9k.LoadFont 
	                RET	NZ	; Return if error loading font
	      	      	  	                
	                LD	IX,font            
	                CALL	G9k.Close
	                
	                LD	IX,font
		        CALL	G9k.SetFont      ; Set font
	                XOR	A,A
	                RET	   	             			              	                

font			VFF_OBJECT
FONT_OFFSET_TABLE	DS	512,0
         		       		
			include "file.asm"
			include "g9klib.asm"
			include "string.asm"
			include "bdos.asm"
			include "bitbuster.asm"
			include "math.asm"
			include "keyboard.asm"
		

NEW_LINE		DB	CR,LF,0
G9BObject		G9B_OBJECT 


FindFirst:
			LD	 B,0
			LD	 IX,fib
			BdosCall _FFIRST
			jp	 nz,Bdos.ExplainError
			ret

FindNext:
			LD	 IX,fib
			BdosCall _FNEXT
			RET
			
fib			FIB

DATA_BUFFER
; Functions and data from here only used during init


fontName		DB    "DIGITAL.VFF",0

PrintHelp:		
			LD	DE,G9B_VIEW_TXT
			CALL    String.PrintAsciiz
			RET

G9B_VIEW_TXT		DB "G9BViewer V0.6",CR,LF,LF
			DB	"Usage:",CR,LF,LF
			DB	"G9BVIEW [D:][PATH]FILENAME.EXT",LF,LF,CR,0
			
NoGfx9kDetected:
			LD	DE,NO_GFX9K_TEXT
			CALL    String.PrintAsciiz
			RET	
			
NO_GFX9K_TEXT		DB	"*** No Gfx9000 detected",LF,CR,0

GetStartPath:
; Input    : DE = Pointer to string buffer(size=64 bytes)
; Ouput    : HL = Pointer to start of last item
;          : DE = Pointer to termination character
; Modifies : AF,BC

			PUSH	  DE
			LD	  HL,.ENV_PROGRAM
			LD	  B,64
			BdosCall  _GENV
			LD	  B,0
			POP	  DE
			BdosCall  _PARSE	; Returns with HL to the begin of the file name
			RET
		
.ENV_PROGRAM		DB 	"PROGRAM",0	

startPath		DS	64,0	